﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TiposComuns.Objectos;
using System.Collections;
using System.Runtime.CompilerServices;

namespace Servidor.Objectos
{
    /// <summary>
    /// Representation of user's friends.
    /// </summary>
    [Serializable]
    public class Friends
    {
        #region Attributes
        private SerializableDictionary<string,Person> friends;      //Confirmed friends
        private SerializableDictionary<string, Person> sent;        //Persons to whom there were sent requests
        private SerializableDictionary<string, Person> received;    //Persons that requested to be friend of the user
        #endregion
        
        #region Modifiers
        public SerializableDictionary<string,Person> FriendList
        {
            [MethodImpl(MethodImplOptions.Synchronized)]
            get { return friends; }

            [MethodImpl(MethodImplOptions.Synchronized)]
            set { friends = value; }
        }

        public SerializableDictionary<string, Person> Received
        {
            [MethodImpl(MethodImplOptions.Synchronized)]
            get { return received; }

            [MethodImpl(MethodImplOptions.Synchronized)]
            set { received = value; }
        }

        public SerializableDictionary<string, Person> Sent
        {
            [MethodImpl(MethodImplOptions.Synchronized)]
            get { return sent; }

            [MethodImpl(MethodImplOptions.Synchronized)]
            set { sent = value; }
        }
        #endregion
        
        #region Constructors
        public Friends()
        {
            this.friends = new SerializableDictionary<string, Person>();
            this.sent = new SerializableDictionary<string, Person>();
            this.received = new SerializableDictionary<string, Person>();
        }
        #endregion

        #region Methods
        [MethodImpl(MethodImplOptions.Synchronized)]
        public bool MayAdd(Person friend)
        {
            return !friends.ContainsKey(friend.Username) && !sent.ContainsKey(friend.Username) && !received.ContainsKey(friend.Username);
        }

        /// <summary>
        /// Returns list of user's friends
        /// </summary>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public List<Person> ListFriends()
        {
            
                List<Person> list = new List<Person>();

                foreach (Person pess in friends.Values)
                {
                    list.Add(pess);
                }

                return list;
            
        }

        /// <summary>
        /// Returns list of sent requests
        /// </summary>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public List<Person> SentRequests()
        {
            
                List<Person> list = new List<Person>();

                foreach (Person pess in sent.Values)
                {
                    list.Add(pess);
                }

                return list;
            
        }

        /// <summary>
        /// Return list of received requests
        /// </summary>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public List<Person> ReceivedRequests()
        {
                List<Person> list = new List<Person>();

                foreach (Person pess in received.Values)
                {
                    list.Add(pess);
                }

                return list;            
        }

        /// <summary>
        /// Accepts a new friend, removing it from the sent requests or the received ones
        /// </summary>
        /// <param name="person">New friend</param>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void AcceptFriend(Person person)
        {
            if (!this.friends.ContainsKey(person.Username))
            {
                this.friends.Add(person.Username, person);
            }
            this.sent.Remove(person.Username);
            this.received.Remove(person.Username);
        }

        /// <summary>
        /// Remove friend
        /// </summary>
        /// <param name="person">Ex friend</param>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void RemoveFriend(Person person)
        {
            this.friends.Remove(person.Username);
        }

        /// <summary>
        /// Reject friend
        /// </summary>
        /// <param name="person">Ex friend</param>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void RejectFriend(Person person)
        {
            this.received.Remove(person.Username);
            this.sent.Remove(person.Username);
        }

        /// <summary>
        /// Add new friendship request sent
        /// </summary>
        /// <param name="person">Person to whom the request was sent</param>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void RequestFriend(Person person)
        {
            if (!this.sent.ContainsKey(person.Username))
            {
                this.sent.Add(person.Username, person);
            }
        }

        /// <summary>
        /// Add new received request
        /// </summary>
        /// <param name="person">Person that sent the request</param>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void ReceiveFriend(Person person)
        {
            if (!this.received.ContainsKey(person.Username))
            {
                this.received.Add(person.Username, person);
            }
        }

        #endregion
    }
}
